package cn.czh0123.service.impl;

import cn.czh0123.dto.UploadImageInfo;
import cn.czh0123.exception.BusinessException;
import cn.czh0123.msg.FileCodeMsg;
import cn.czh0123.service.IMinioService;
import com.google.common.collect.Maps;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.imaging.ImageInfo;
import org.apache.commons.imaging.Imaging;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: czh
 * @description:
 * @date: 2024/4/8 22:24
 */
@Slf4j
@Service
public class MinioServiceImpl implements IMinioService {

    @Value("${minio.bucketName}")
    private String bucketName;

    @Resource
    private MinioClient minioClient;

    private static final Map<String, String> MIME_TYPE_MAP = Maps.newHashMap();

    static {
        MIME_TYPE_MAP.put("jpg", "image/jpeg");
        MIME_TYPE_MAP.put("jpeg", "image/jpeg");
        MIME_TYPE_MAP.put("png", "image/png");
        MIME_TYPE_MAP.put("gif", "image/gif");
    }

    @Override
    public UploadImageInfo uploadFile(String baseDirectory, MultipartFile file) {
        UploadImageInfo uploadImageInfo = new UploadImageInfo();
        // 将MultipartFile的InputStream缓存到ByteArrayOutputStream
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            IOUtils.copy(file.getInputStream(), baos);
        } catch (IOException e) {
            log.error("上传文件失败", e);
        }
        byte[] bytes = baos.toByteArray();

        InputStream inputStream;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            throw new BusinessException(FileCodeMsg.UPLOAD_FAILURE);
        }
        String imageName = file.getOriginalFilename();
        if (imageName == null) {
            throw new BusinessException(FileCodeMsg.INVALID_IMAGE_NAME);
        }

        LocalDate currentDate = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String dateDirectory = currentDate.format(formatter);

        String uuid = UUID.randomUUID().toString();
        String objectName = String.format("/%s/%s/%s_%s", baseDirectory, dateDirectory, uuid, imageName);

        // 提取文件扩展名
        Pattern extensionPattern = Pattern.compile("\\.([^.]+)$");
        Matcher matcher = extensionPattern.matcher(imageName);
        if (!matcher.find()) {
            throw new BusinessException(FileCodeMsg.INVALID_IMAGE_NAME);
        }
        String fileExtension = matcher.group(1).toLowerCase();

        // 根据文件扩展名获取MIME类型
        String contentType = MIME_TYPE_MAP.get(fileExtension);
        if (contentType == null) {
            throw new BusinessException(FileCodeMsg.INVALID_IMAGE_FORMAT);
        }

        PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .stream(inputStream, -1, 10485760) // 这里需要输入流的大小，如果未知可用-1
                .contentType(contentType)
                .build();
        try {
            minioClient.putObject(putObjectArgs);
        } catch (Exception e) {
            throw new BusinessException(FileCodeMsg.UPLOAD_FAILURE);
        }
        uploadImageInfo.setUrl("/" + bucketName + objectName);

        // 使用缓存的数据创建新的InputStream以获取图像信息
        try {
            InputStream infoStream = new ByteArrayInputStream(bytes);
            ImageInfo imageInfo = Imaging.getImageInfo(infoStream, file.getOriginalFilename());
            int width = imageInfo.getWidth();
            int height = imageInfo.getHeight();
            uploadImageInfo.setWidth(width);
            uploadImageInfo.setHeight(height);
        } catch (Exception e) {
            log.error("获取图片信息失败", e);
        }

        // 获取图片大小
        uploadImageInfo.setSize(file.getSize());
        return uploadImageInfo;
    }

}
